package com.pudutech.bluetoothdemo.bluetooth
import android.annotation.TargetApi
import android.app.Activity
import android.bluetooth.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.nfc.Tag
import android.os.Build
import android.os.Handler
import android.os.Message
import android.os.ParcelUuid
import android.util.Log
import android.widget.Toast
import java.io.IOException
import java.io.InputStream
import java.lang.reflect.Field
import java.lang.reflect.InvocationTargetException
import java.util.*


/*
 *  @项目名：  BluetoothTest
 *  @创建者:   cai
 *  @创建时间:  2018/5/22 13:08
 *  @描述：    TODO
 */
object BluetoothUtils {
    private var TAG="BluetoothUtils"


    private var mSocket: BluetoothSocket? = null
    private var mReadThread: ReadThread? = null
    private var mServerSocket: BluetoothServerSocket? = null
    private var mClientThread: ClientThread? = null
    private var mServerThread: ServerThread? = null

    const val HANDLER_RECEIVE_MESSAGE = 101

    /**
     * 获取蓝牙适配器
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    fun getBluetoothAdapter(context: Context): BluetoothAdapter {
        var mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()

        val mBluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager//获取蓝牙管理器
        if (mBluetoothManager != null) {
            mBluetoothAdapter = mBluetoothManager.adapter //获取蓝牙适配器
        }
        return mBluetoothAdapter
    }

    /**
     * 检查蓝牙是否打开(是否可用)
     */
    fun checkBleDevice(context: Context): Boolean {
        if (BluetoothUtils.getBluetoothAdapter(context) == null)
            return false
        return getBluetoothAdapter(context).isEnabled
    }

    /**
     * 尝试打开蓝牙
     */
    fun openBluetooth(context: Context) {
        openBluetooth(context, 3600)//3600为蓝牙设备可见时间
    }

    /**
     * 尝试打开蓝牙
     */
    fun openBluetooth(context: Context, time: Int) {
        getBluetoothAdapter(context).enable()
        val enable = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)
        enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, time)
        context.startActivity(enable)
    }

    /**
     * 关闭蓝牙
     */
    fun closeBluetooth(context: Context) {
        getBluetoothAdapter(context).disable()
    }

    /**
     * 尝试搜索可见蓝牙设备
     */
    fun searchBluetooth(context: Context): Boolean {
        //如果当前发现了新的设备，则停止继续扫描，当前扫描到的新设备会通过广播推向新的逻辑
        if (getBluetoothAdapter(context).isDiscovering()) {
            stopSearthBltDevice(context)
            return false
        }
        return getBluetoothAdapter(context).startDiscovery()
    }

    /**
     * 尝试停止搜索
     */
    fun stopSearthBltDevice(context: Context): Boolean {
        return getBluetoothAdapter(context).cancelDiscovery()
    }

    /**
     * 注册蓝牙广播
     */
    fun registerBluetoothReceiver(activity: Activity, receiver: BroadcastReceiver) {
        val intent = IntentFilter()
        intent.addAction(BluetoothDevice.ACTION_FOUND)//搜索发现设备
        intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)//状态改变
        intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)//行动扫描模式改变了
        intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)//动作状态发生了变化
        intent.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST)
        activity.registerReceiver(receiver, intent)
    }

    /**
     * 反注册广播
     */
    fun unregisterReceiver(context: Context, receiver: BroadcastReceiver) {
        context.unregisterReceiver(receiver)
        if (getBluetoothAdapter(context) != null)
            getBluetoothAdapter(context).cancelDiscovery()
    }


    /**
     *打开客户端线程
     */
    fun startClientThread(device: BluetoothDevice) {
        if (mClientThread == null) {
            synchronized(this) {
                if (mClientThread == null) {
                    mClientThread = ClientThread(device, getUUID())
                    mClientThread?.start()
                }
            }
        }
    }

    /**
     * 打开服务端线程
     */
    fun startServerThread(context: Context) {
        if (mServerThread == null) {
            synchronized(this) {
                if (mServerThread == null) {
                    mServerThread = ServerThread(context, getUUID())
                    mServerThread?.start()
                }
            }
        }else{
            Log.v(TAG,"")
        }

    }

    /**
     * 发送数据
     */
    fun sendMessageHandle(context: Context, msg: String) {
        if (mSocket == null) {
            Toast.makeText(context, "没有连接", Toast.LENGTH_SHORT).show()
            return
        }
        try {
            val os = mSocket?.getOutputStream()
            os?.write(msg.toByteArray())
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    /**
     * 停止客户端连接
     */
    fun shutdownClient() {
        object : Thread() {
            override fun run() {
                if (mClientThread != null) {
                    mClientThread?.interrupt()
                }
                if (mReadThread != null) {
                    mReadThread?.interrupt()
                }
                if (mSocket != null) {
                    try {
                        mSocket?.close()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }
                }
            }
        }.start()
    }

    /**
     * 停止服务器
     */
    fun shutdownServer() {
        object : Thread() {
            override fun run() {
                if (mServerThread != null) {
                    mServerThread?.interrupt()
                }
                if (mReadThread != null) {
                    mReadThread?.interrupt()
                }
                try {
                    if (mSocket != null) {
                        mSocket?.close()
                    }
                    if (mServerSocket != null) {
                        mServerSocket?.close()
                    }
                } catch (e: IOException) {
                    e.printStackTrace()
                }

            }
        }.start()
    }

    /**
     * 反射获取本地蓝牙地址
     */
    fun getBtAddressByReflection(): String? {
        val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        var field: Field?
        try {
            field = BluetoothAdapter::class.java.getDeclaredField("mService")
            field!!.setAccessible(true)
            val bluetoothManagerService = field!!.get(bluetoothAdapter) ?: return null
            val method = bluetoothManagerService.javaClass.getMethod("getAddress")
            if (method != null) {
                val obj = method.invoke(bluetoothManagerService)
                if (obj != null) {
                    return obj.toString()
                }
            }
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        } catch (e: NoSuchMethodException) {
            e.printStackTrace()
        } catch (e: InvocationTargetException) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 获取UUID
     */
    fun getUUID(): UUID {
        var uuid: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
//        try {
//            val getUuidsMethod = BluetoothAdapter::class.java.getDeclaredMethod("getUuids")
//            val uuids = getUuidsMethod.invoke(BluetoothAdapter.getDefaultAdapter(), null) as Array<ParcelUuid>
//            uuid = uuids[0].uuid
//        } catch (e: Exception) {
//            e.printStackTrace()
//        }
        return uuid
    }

    /**
     * 客户端线程
     */
    class ClientThread(device: BluetoothDevice, uuid: UUID) : Thread() {
        private lateinit var uuid: UUID

        init {
            this.uuid = uuid
            mSocket = device.createRfcommSocketToServiceRecord(uuid)
        }

        override fun run() {
            try {
                mSocket?.connect()
            } catch (e: IOException) {
                e.printStackTrace()
            }

        }
    }

    /**
     * 服务器线程
     */
    class ServerThread : Thread {
        private lateinit var context: Context
        private lateinit var uuid: UUID
        private var serverName = "defServerName"

        constructor(context: Context, uuid: UUID) {
            ServerThread(context,uuid,serverName)
        }

        constructor(context: Context, uuid: UUID, name: String) {
            this.context = context
            this.uuid = uuid
            this.serverName = name

            mServerSocket = getBluetoothAdapter(context).listenUsingRfcommWithServiceRecord(serverName,
                uuid)
        }

        override fun run() {
            try {
                /* 接受客户端的连接请求 */
                mSocket = mServerSocket?.accept()
                mReadThread = ReadThread()
                mReadThread?.start()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

    var mReadListener:ReadListener?=null
    /**
     * 读取数据线程.
     * 空参构造使用EventBus传递收到的消息.
     * 有参构造使用Handler传递收到的消息.
     */
    class ReadThread : Thread {
        private var handler: Handler? = null

        constructor() {
        }

        constructor(handler: Handler) {
            this.handler = handler
        }

        override fun run() {
            var input: InputStream? = null
            try {
                val buffer = ByteArray(1024)
                input = (mSocket as BluetoothSocket).getInputStream()
                while (true) {
                    var bytes = input.read(buffer)
                    if (bytes > 0) {
                        val buf_data = ByteArray(bytes)
                        for (i in 0..bytes - 1) {
                            buf_data[i] = buffer[i]
                        }
                        val s = String(buf_data)

                        if (handler != null) {
                            val msg: Message = Message()
                            msg.what = HANDLER_RECEIVE_MESSAGE
                            msg.obj = s
                            handler!!.sendMessage(msg)
                        }
                        //处理蓝牙通信读取到的  内容
//                        EventBus.getDefault().post(s)
                        mReadListener?.readMessage(s)
                    }
                }
            } catch (e1: IOException) {
                e1.printStackTrace()
            } finally {
                try {
                    if (input != null)
                        input.close()
                } catch (e1: IOException) {
                    e1.printStackTrace()
                }
            }

        }
    }

    /**
     * 绑定蓝牙
     */
    object Bonde {

        /**
         * 开始匹配
         */
        fun createBond(btDevice: BluetoothDevice): Boolean {
            return btDevice.createBond()
        }

        /**
         * 与设备解除配对
         */
        @Throws(Exception::class)
        fun removeBond(btClass: Class<*>, btDevice: BluetoothDevice): Boolean {
            val removeBondMethod = btClass.getMethod("removeBond")
            val returnValue = removeBondMethod.invoke(btDevice) as Boolean
            return returnValue
        }


        @Throws(Exception::class)
        fun setPin(btClass: Class<out BluetoothDevice>, btDevice: BluetoothDevice,
                   str: String): Boolean {
            try {
                val removeBondMethod = btClass.getDeclaredMethod("setPin",
                    *arrayOf<Class<*>>(ByteArray::class.java))
                val returnValue = removeBondMethod.invoke(btDevice,
                    arrayOf<Any>(str.toByteArray())) as Boolean
                Log.e("returnValue", "" + returnValue)
            } catch (e: SecurityException) {
                e.printStackTrace()
            } catch (e: IllegalArgumentException) {
                e.printStackTrace()
            } catch (e: Exception) {
                e.printStackTrace()
            }

            return true

        }

        /**
         * 取消用户输入
         */
        @Throws(Exception::class)
        fun cancelPairingUserInput(btClass: Class<*>,
                                   device: BluetoothDevice): Boolean {
            val createBondMethod = btClass.getMethod("cancelPairingUserInput")
            //        cancelBondProcess(btClass, device);
            val returnValue = createBondMethod.invoke(device) as Boolean
            return returnValue
        }

        /**
         * 取消配对
         */
        @Throws(Exception::class)
        fun cancelBondProcess(btClass: Class<*>,
                              device: BluetoothDevice): Boolean {
            val createBondMethod = btClass.getMethod("cancelBondProcess")
            val returnValue = createBondMethod.invoke(device) as Boolean
            return returnValue
        }

        /**
         * 确认配对
         */
        @Throws(Exception::class)
        fun setPairingConfirmation(btClass: Class<*>, device: BluetoothDevice, isConfirm: Boolean) {
            val setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation", Boolean::class.java)
            setPairingConfirmation.invoke(device, isConfirm)
        }


        /**
         * 取得所有方法
         * @param clsShow
         */
        fun printAllInform(clsShow: Class<*>) {
            try {
                // 取得所有方法
                val hideMethod = clsShow.methods
                var i = 0
                while (i < hideMethod.size) {
                    Log.e("method name", hideMethod[i].name + ";and the i is:"
                            + i)
                    i++
                }
                // 取得所有常量
                val allFields = clsShow.fields
                i = 0
                while (i < allFields.size) {
                    Log.e("Field name", allFields[i].name)
                    i++
                }
            } catch (e: SecurityException) {
                e.printStackTrace()
            } catch (e: IllegalArgumentException) {
                e.printStackTrace()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    class BluetoothBroadcastReceiver : BroadcastReceiver() {
        //接收
        override fun onReceive(context: Context, intent: Intent) {
            val action = intent.getAction()
            var device: BluetoothDevice?
            // 搜索发现设备时，取得设备的信息；注意，这里有可能重复搜索同一设备
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)

            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                when (device?.bondState) {
                    BluetoothDevice.BOND_BONDING//正在配对
                    -> {
                        //正在配对......
                    }
                    BluetoothDevice.BOND_BONDED//配对结束
                    -> {
                        //完成配对
                        //startMessageTest(device)
                    }
                    BluetoothDevice.BOND_NONE//取消配对/未配对
                    -> {
                        //取消配对
                    }
                }

            }
        }
    }
}
